#include "../include/cat-audio.hpp"
#include "../include/util/platform.hpp"
#include <SFML/Audio.hpp>
#include <thread>
#include <queue>
#include "../include/util/cmem.hpp"

struct SoundData{
	std::string SoundPath;
	bool isStop = false;
};

class CatAudio {
public:
    static CatAudio* GetInstance();

    static void ReleaseInstance();

	void Start();

	void Stop();

	void PushSound(const char* soundPath,bool isStop);

	void SetSlient(bool _isSlient) {
		isSlient = _isSlient;
	}

private:
	CatAudio();

	~CatAudio();

	void Run();

	std::thread* th;
	bool isExist;
	bool isSlient;

	std::queue<SoundData> data;
};

namespace {

    CatAudio* s_instance = NULL;
}

CatAudio::CatAudio() :
	isExist(false),
	th(NULL) ,
	isSlient(false)
{

}

CatAudio::~CatAudio() {

}

CatAudio* CatAudio::GetInstance()
{
	if (s_instance == NULL) {
		s_instance = new CatAudio();
	}
	return s_instance;
}

void CatAudio::ReleaseInstance()
{
	if (s_instance != NULL) {
		delete s_instance;
	}

	s_instance = NULL;
}

void CatAudio::Start()
{
	isExist = false;
	th = new std::thread(&CatAudio::Run, this);
}

void CatAudio::Stop()
{
	isExist = true;
	th->join();
}

void CatAudio::PushSound(const char* soundPath, bool isStop)
{
	if(!isSlient)
	data.push({ std::string(soundPath),isStop});
}


void CatAudio::Run()
{
	int index = 0;
	sf::Sound sound[10]; 
	sf::SoundBuffer buffer[10];
	while (!isExist)
	{
		if (data.empty()) {
			sf::sleep(sf::milliseconds(100));
			continue;
		}
		if (data.front().isStop)
			for (int i = 0; i < 10; i++) {
				sound[i].stop();
			}

		char* sound_data = NULL;
		size_t sound_data_size = 0;
		sound_data= LoadFileAsBytesEX(data.front().SoundPath.c_str(), sound_data_size);

		if (sound_data == NULL)
			continue;

		if (!buffer[index].loadFromMemory(sound_data, sound_data_size))
		{
			bfree(sound_data);
			data.pop();
			continue;
		}
		sound[index].setBuffer(buffer[index]);
		sound[index].play();
		data.pop();
		index++;
		if (index == 10)
			index = 0;

		bfree(sound_data);
	}

	while(!data.empty())data.pop();
}

void cat_audio_play_thread_start()
{
	CatAudio::GetInstance()->Start();
}

void cat_audio_play_thread_stop()
{
	CatAudio::GetInstance()->Stop();
	CatAudio::ReleaseInstance();
}

void cat_audio_play_sound(const char* filename,bool _stoplastsound)
{
	CatAudio::GetInstance()->PushSound(filename,_stoplastsound);
}

void cat_audio_set_silent(bool _issilent)
{
	CatAudio::GetInstance()->SetSlient(_issilent);
}
